home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
684
/
684.xpi
/
chrome
/
fireftp.jar
/
content
/
js
/
local
/
localDirTree.js
next >
Wrap
Text File
|
2008-08-01
|
25KB
|
571 lines
var localDirTree = {
data : new Array(),
rowCount : 0,
exceptions : new Array(),
dirtyList : new Array(),
ignoreSelect : false,
getCellText : function(row, column) { return this.data[row].leafName; },
getLevel : function(row) { return this.data[row].level; },
getParentIndex : function(row) { return this.data[row].parentIndex; },
getImageSrc : function(row, col) { },
getColumnProperties : function(colid, col, props) { },
getRowProperties : function(row, props) { },
hasNextSibling : function(row, nextrow) { return this.data[row].hasNext; },
isContainer : function(row) { return true; },
isContainerEmpty : function(row) { return this.data[row].empty; },
isContainerOpen : function(row) { return this.data[row].open; },
isSeparator : function(row) { return false; },
isSorted : function(row) { return false; },
setTree : function(treebox) { this.treebox = treebox; },
getCellProperties : function(row, col, props) {
if (row >= 0 && row < this.data.length && this.data[row]) {
if (this.data[row].isHidden) {
props.AppendElement(gAtomService.getAtom("hidden"));
}
}
},
toggleOpenState : function(row, suppressChange) {
var doOpen = true;
if (this.isContainerOpen(row)) {
doOpen = false;
var level = this.data[row].level;
var lastChild = row;
while (lastChild + 1 < this.rowCount && this.data[lastChild + 1].level > level) { // find last index in same level as collapsed dir
++lastChild;
}
this.data[row].children = this.data.splice(row + 1, lastChild - row); // get rid of subdirectories from view
this.updateParentIndices();
this.rowCount = this.data.length;
this.treebox.rowCountChanged(row, -(lastChild - row));
this.data[row].open = false;
this.treebox.invalidateRow(row); // update row
var localPathSlash = gLocalPath.value + (gLocalPath.value.charAt(gLocalPath.value.length - 1) != gSlash ? gSlash : '');
var dataPathSlash = this.data[row].path + (this.data[row].path.charAt(this.data[row].path.length - 1) != gSlash ? gSlash : '');
if (localPathSlash.indexOf(dataPathSlash) == 0 && gLocalPath.value != this.data[row].path
&& gLocalPath.value.match(gSlash == "/" ? /\x2f/g : /\x5c/g ).length > this.data[row].level && !suppressChange) {
gLocalPath.value = this.data[row].path; // we were in a subdirectory and we collapsed
this.selection.select(row);
this.treebox.ensureRowIsVisible(row);
localTree.updateView();
} else if (gLocalPath.value == this.data[row].path) {
this.selection.select(row);
this.treebox.ensureRowIsVisible(row);
}
} else {
for (var x = 0; x < this.dirtyList.length; ++x) { // see if the row is dirty
if (this.dirtyList[x] == this.data[row].path) {
this.dirtyList.splice(x, 1);
this.data[row].children = null;
break;
}
}
if (this.data[row].children) { // see if any of the rows children are dirty
for (var x = 0; x < this.dirtyList.length; ++x) {
var found = false;
for (var y = this.data[row].children.length - 1; y >= 0; --y) {
if (this.data[row].children[y].path == this.dirtyList[x]) {
found = true;
this.data[row].children[y].children = null;
this.data[row].children[y].open = false;
this.data[row].children[y].empty = false;
} else if (this.data[row].children[y].path.indexOf(this.dirtyList[x]
+ (this.dirtyList[x].charAt(this.dirtyList[x].length - 1) != gSlash ? gSlash : '')) == 0) {
found = true;
this.data[row].children.splice(y, 1);
}
}
if (found) {
this.dirtyList.splice(x, 1);
}
}
}
if (this.data[row].children) { // stored from before
for (var x = this.data[row].children.length - 1; x >= 0; --x) {
this.data.splice(row + 1, 0, this.data[row].children[x]);
}
this.updateParentIndices();
this.rowCount = this.data.length;
this.treebox.rowCountChanged(row + 1, this.data[row].children.length);
this.data[row].children = null;
this.data[row].open = true;
this.treebox.invalidateRow(row);
} else { // get data for this directory
var newDirectories = new Array();
try {
var dir = localFile.init(this.data[row].path);
var entries = dir.directoryEntries;
while (entries.hasMoreElements()) {
var file = entries.getNext().QueryInterface(Components.interfaces.nsILocalFile);// get subdirectories
var isParent = false;
var isException = false;
var filePathSlash = file.path + (file.path.charAt(file.path.length - 1) != gSlash ? gSlash : '');
if (file.exists() && localFile.testSize(file) && file.isDirectory() && this.findDirectory) { // we're navigating to a directory that might be hidden
var findDirectorySlash = this.findDirectory.path
+ (this.findDirectory.path.charAt(this.findDirectory.path.length - 1) != gSlash ? gSlash : '');
if (gSlash == "/") {
isParent = findDirectorySlash.indexOf(filePathSlash) == 0;
} else {
isParent = findDirectorySlash.toLowerCase().indexOf(filePathSlash.toLowerCase()) == 0;
}
if (isParent) {
this.exceptions.push(this.findDirectory);
}
}
for (var x = 0; x < this.exceptions.length; ++x) {
var exceptionsSlash = this.exceptions[x].path + (this.exceptions[x].path.charAt(this.exceptions[x].path.length - 1) != gSlash ? gSlash : '');
if (gSlash == "/") {
isException = exceptionsSlash.indexOf(filePathSlash) == 0;
} else {
isException = exceptionsSlash.toLowerCase().indexOf(filePathSlash.toLowerCase()) == 0;
}
if (isException) {
break;
}
}
if (file.exists() && localFile.testSize(file) && file.isDirectory() && (!file.isHidden() || gFtp.hiddenMode || isParent || isException)) {
newDirectories.push(file);
}
}
} catch (ex) {
debug(ex);
error(gStrbundle.getString("noPermission"));
}
if (newDirectories.length == 0) { // no subdirectories
this.data[row].empty = true;
this.data[row].open = false;
} else { // has subdirectories
for (var x = 0; x < newDirectories.length; ++x) {
newDirectories[x] = { open : false,
empty : false,
hasNext : true,
parentIndex : -1,
children : null,
path : newDirectories[x].path,
leafName : newDirectories[x].leafName,
parent : newDirectories[x].parent ? newDirectories[x].parent.path : "",
isHidden : newDirectories[x].isHidden(),
level : newDirectories[x].path.match( gSlash == "/" ? /\x2f/g : /\x5c/g).length,
sortPath : newDirectories[x].path.replace(gSlash == "/" ? /\x2f/g : /\x5c/g, "\x01").toLowerCase() };
}
newDirectories.sort(directorySort);
newDirectories[newDirectories.length - 1].hasNext = false; // last one doesn't have a next
for (var x = newDirectories.length - 1; x >= 0; --x) {
this.data.splice(row + 1, 0, newDirectories[x]);
}
this.updateParentIndices();
this.rowCount = this.data.length;
this.treebox.rowCountChanged(row + 1, newDirectories.length);
this.data[row].open = true;
}
this.treebox.invalidateRow(row);
}
}
$('localdirname').removeAttribute('flex'); // horizontal scrollbars, baby!
var max = 125;
for (var z = 0; z < this.rowCount; ++z) { // this is what we CS folk like to call a TOTAL HACK
var x = { }; var y = { }; var width = { }; var height = { }; // but, hey, it works so bite me
this.treebox.getCoordsForCellItem(z, this.treebox.columns["localdirname"], "text", x, y, width, height);
if (x.value + width.value + 125 > max) {
max = x.value + width.value + 125;
}
}
//if (doOpen) {
this.readjustHorizontalPosition(row);
//}
$('localdirname').setAttribute('width', max);
},
readjustHorizontalPosition : function(row) {
var x = { }; var y = { }; var width = { }; var height = { };
var first = this.treebox.getFirstVisibleRow() > 0 ? this.treebox.getFirstVisibleRow() : 0;
var last = this.treebox.getLastVisibleRow() - 1 >= 0 ? this.treebox.getLastVisibleRow() - 1 : 0;
this.treebox.getCoordsForCellItem(row != -1 ? row : 0, this.treebox.columns["localdirname"], "text", x, y, width, height);
this.treebox.scrollToHorizontalPosition(this.treebox.horizontalPosition + x.value - 60 >= 0 ? this.treebox.horizontalPosition + x.value - 60 : 0);
var self = this;
var func = function() {
self.treebox.ensureRowIsVisible(last);
self.treebox.ensureRowIsVisible(first);
};
if (first < this.data.length) {
setTimeout(func, 0);
}
},
addDirtyList : function(path) {
for (var x = 0; x < this.dirtyList.length; ++x) {
if (this.dirtyList[x] == path) {
return;
}
}
this.dirtyList.push(path);
},
updateParentIndices : function() {
for (var x = 0; x < this.data.length; ++x) {
this.data[x].parentIndex = this.indexOfPath(this.data[x].parent); // ah, beautiful
}
},
indexOfPath : function(path) { // binary search to find a path in the localDirTree
if (!path) {
return -1;
}
var left = 0;
var right = this.data.length - 1;
var origPath = path;
path = path.replace(gSlash == "/" ? /\x2f/g : /\x5c/g, "\x01").toLowerCase(); // make '/' less than everything (except null really)
while (left <= right) {
var mid = Math.floor((left + right) / 2);
var dataPath = this.data[mid].sortPath;
if (gSlash == "/" && (this.data[mid].path == origPath || this.data[mid].path + "/" == origPath || this.data[mid].path == origPath + "/")) {
return mid;
} else if (dataPath == path || dataPath + "\x01" == path || dataPath == path + "\x01") { // kind of complicated but what can you do
if (gSlash == "\\") {
return mid;
} else {
break;
}
} else if (path < dataPath) {
right = mid - 1;
} else if (path > dataPath) {
left = mid + 1;
}
}
if (gSlash == "/") {
for (var x = 0; x < this.data.length; ++x) { // last ditch effort b/c of we have to account for case
if (this.data[x].path == origPath || this.data[x].path + "/" == origPath || this.data[x].path == origPath + "/") {
return x;
}
}
}
return -1;
},
cdup : function() {
var parentIndex = this.getParentIndex(this.selection.currentIndex);
if (parentIndex != -1) {
this.selection.select(parentIndex);
}
},
findDirectory : null,
changeDir : function(path, retry) {
if (path.indexOf("\\") == 0) { // we can't handle network drives for now
error(gStrbundle.getString("noPermission"));
return;
}
gLocalPath.value = path;
if (this.data.length == 0 || this.data[0].path.charAt(0) != gLocalPath.value.charAt(0)) { // if dirTree is empty or we're switching to a new drive
var thePath; // we restart the tree
if (gLocalPath.value.indexOf('/') == 0) { // linux
thePath = "/";
gSlash = "/";
} else { // windows
if (gLocalPath.value.indexOf('\\') == -1) {
gLocalPath.value += "\\";
}
thePath = gLocalPath.value.substring(0, gLocalPath.value.indexOf('\\') + 1);
gSlash = "\\";
}
try { // make sure we have a valid drive
var dir = localFile.init(thePath);
var entries = dir.directoryEntries;
} catch (ex) {
error(gStrbundle.getString("noPermission"));
return;
}
var oldRowCount = this.rowCount;
this.data = new Array();
this.rowCount = 0;
this.treebox.rowCountChanged(0, -oldRowCount);
this.data.push({ open : false,
empty : false,
hasNext : false,
parentIndex : -1,
children : null,
path : thePath,
leafName : thePath,
parent : "",
isHidden : false,
level : 0,
sortPath : thePath.replace(gSlash == "/" ? /\x2f/g : /\x5c/g, "\x01").toLowerCase() });
this.rowCount = 1;
this.treebox.rowCountChanged(0, 1);
}
if (gSlash == "/") { // error checking here for correct values in path
gLocalPath.value = gLocalPath.value.replace(/\x5c/g, "/"); // linux shouldn't have backslashes
} else {
gLocalPath.value = gLocalPath.value.replace(/\x2f/g, "\\"); // windows shouldn't have forward slashes
}
gLocalPath.value = gLocalPath.value.replace(/\\\.\.\\/g, "\\"); // "\..\asdf"; doing relative paths not allowed
gLocalPath.value = gLocalPath.value.replace(/\\\.\\/g, "\\"); // "\.\asdf"
gLocalPath.value = gLocalPath.value.replace(/\\\.\.$/g, "\\"); // "\.."
gLocalPath.value = gLocalPath.value.replace(/\\\.$/g, "\\"); // "\."
gLocalPath.value = gLocalPath.value.replace(/\/\.\.\//g, "/"); // "/../asdf"
gLocalPath.value = gLocalPath.value.replace(/\/\.\//g, "/"); // "/./asdf"
gLocalPath.value = gLocalPath.value.replace(/\/\.\.$/g, "/"); // "/.."
gLocalPath.value = gLocalPath.value.replace(/\/\.$/g, "/"); // "/."
if (gLocalPath.value != '/' && gLocalPath.value.charAt(gLocalPath.value.length - 1) == gSlash) {
gLocalPath.value = gLocalPath.value.substring(0, gLocalPath.value.length - 1); // trim slashes at the end - ruins levels in dir
}
if (gSlash == "\\" && gLocalPath.value.indexOf('\\') == -1) { // if it's windows we add a slash to it: 'c:'->'c:\'
gLocalPath.value += "\\";
}
if (gSlash == "/" && gLocalPath.value.charAt(0) != '/') { // linux path has to start with '/'
gLocalPath.value = '/' + gLocalPath.value;
}
var bestMatch;
var bestPath;
var localPathLevel = gLocalPath.value.match(gSlash == "/" ? /\x2f/g : /\x5c/g ).length;
for (var x = 0; x < this.data.length; ++x) { // open parent directories til we find the directory
for (var y = this.data.length - 1; y >= x; --y) {
if ((gLocalPath.value.indexOf(this.data[y].path) == 0
|| (gSlash == "\\" && gLocalPath.value.toLowerCase().indexOf(this.data[y].path.toLowerCase()) == 0))
&& (this.getLevel(y) < localPathLevel || gLocalPath.value == this.data[y].path)) {
x = y;
bestMatch = y;
bestPath = this.data[y].path;
break;
}
}
if (gLocalPath.value.indexOf(this.data[x].path) == 0
|| (gSlash == "\\" && gLocalPath.value.toLowerCase().indexOf(this.data[x].path.toLowerCase()) == 0)) {
var dirty = false;
for (var z = 0; z < this.dirtyList.length; ++z) {
if (this.dirtyList[z] == this.data[x].path) {
dirty = true;
break;
}
}
this.ignoreSelect = true;
if (this.data[x].open && dirty) {
this.toggleOpenState(x);
this.toggleOpenState(x);
}
if (this.data[x].empty && dirty) {
this.data[x].empty = false;
this.treebox.invalidateRow(x);
}
if (!this.data[x].open && (gLocalPath.value != this.data[x].path || x == 0)) {
this.toggleOpenState(x);
}
this.ignoreSelect = false;
if (gLocalPath.value == this.data[x].path
|| (gSlash == "\\" && gLocalPath.value.toLowerCase() == this.data[x].path.toLowerCase())) {
gLocalPathFocus = gLocalPath.value; // directory approved
gFormHistory.addEntry(gLocalPath.getAttribute("autocompletesearchparam"), gLocalPath.value);
var sString = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
sString.data = gLocalPath.value;
gPrefs.setComplexValue("folder", Components.interfaces.nsISupportsString, sString); // remember last directory
localTree.updateView();
this.readjustHorizontalPosition(this.selection.currentIndex);
if (gTreeSync && !gTreeSyncManager) {
treeSyncManager(true);
} else {
gTreeSyncManager = false;
}
return;
}
}
}
if (gTreeSyncManager) {
gTreeSyncManager = false;
if (bestMatch) {
gLocalPath.value = bestPath;
gLocalPathFocus = bestPath;
localTree.updateView();
}
return;
}
var findDirectory = localFile.init(gLocalPath.value); // we didn't find the directory above
if (localFile.verifyExists(findDirectory) && findDirectory.isDirectory() && (!retry || gLocalPath.value != path)) {
this.findDirectory = findDirectory;
var tempPath = gLocalPath.value;
this.selection.select(bestMatch); // it's possible the directory was added externally
localTree.refresh(true); // and we don't have it on our dir list
this.findDirectory = null;
this.changeDir(tempPath, true);
}
},
select : function(event) {
if (this.ignoreSelect) {
return;
}
var index = this.selection.currentIndex;
if (index >= 0 && index < this.data.length && this.data[index].path != gLocalPath.value) {
this.changeDir(this.data[index].path);
}
},
click : function(event) { // this is a special case: if we want the search to go away
var index = this.selection.currentIndex;
if (index >= 0 && index < this.data.length && (this.data[index].path == gLocalPath.value && localTree.searchMode)) {
this.changeDir(this.data[index].path);
}
},
keyPress : function(event) {
if (event.keyCode == 8) { // backspace
this.cdup();
} else if (event.keyCode == 116) { // F5
event.preventDefault();
localTree.refresh(false, true);
}
},
canDrop : function(index, orient) {
if (index == -1 || orient != 0 || !dragObserver.origin || dragObserver.origin == "external") {
return false;
}
if (dragObserver.origin.indexOf('remote') != -1 && !gFtp.isConnected) {
return false;
}
if (dragObserver.origin == 'localtreechildren') { // can't move into a subdirectory of itself
for (var x = 0; x < localTree.rowCount; ++x) {
var dataPathSlash = this.data[index].path + (this.data[index].path.charAt(this.data[index].path.length - 1) != gSlash ? gSlash : '');
var localTreeSlash = localTree.data[x].path + (localTree.data[x].path.charAt(localTree.data[x].path.length - 1) != gSlash ? gSlash : '');
if (localTree.selection.isSelected(x) && ((dataPathSlash.indexOf(localTreeSlash) == 0 && localTree.data[x].isDirectory())
|| this.data[index].path == localTree.data[x].parent.path
|| this.data[index].path == localTree.data[x].parent.path + gSlash)) {
return false;
}
}
}
return true;
},
drop : function(index, orient) {
if (dragObserver.origin == 'localtreechildren') {
localTree.cut();
localTree.paste(this.data[index].path);
} else if (dragObserver.origin == 'remotetreechildren') {
var anyFolders = false;
for (var x = 0; x < remoteTree.rowCount; ++x) {
if (remoteTree.selection.isSelected(x) && remoteTree.data[x].isDirectory()) {
anyFolders = true;
break;
}
}
if (anyFolders && this.data[index].path != gLocalPath.value) {
var self = this;
var path = this.data[index].path;
var localPath = gLocalPath.value;
var func = function() { self.dropCallback(path, localPath); };
ftpObserver.extraCallback = func;
}
var transferObj = new transfer();
transferObj.localRefresh = gLocalPath.value;
transferObj.start(true, '', this.data[index].path, '');
}
},
dropCallback : function(newParent, localPath) {
var refreshIndex = this.indexOfPath(newParent);
if (refreshIndex != -1) {
if (this.data[refreshIndex].open) {
this.toggleOpenState(refreshIndex, true); // close it up
this.data[refreshIndex].children = null; // reset its children
this.toggleOpenState(refreshIndex); // and open it up again
} else {
this.data[refreshIndex].children = null; // reset its children
this.data[refreshIndex].empty = false;
this.treebox.invalidateRow(refreshIndex);
}
var refreshIndex2 = this.indexOfPath(localPath);
if (refreshIndex2 == -1) {
this.changeDir(localPath);
} else {
this.selection.select(refreshIndex2);
}
} else {
this.addDirtyList(newParent);
}
}
};